package com.xuebusi.toutiao.admin.api.common.interceptor;

import com.xuebusi.toutiao.admin.api.common.enums.TokenEnum;
import com.xuebusi.toutiao.admin.api.common.exception.CustomException;
import com.xuebusi.toutiao.admin.api.common.result.JwtToken;
import com.xuebusi.toutiao.admin.api.common.util.JwtUtil;
import com.xuebusi.toutiao.admin.api.user.entity.UserEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.AsyncHandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 拦截器
 */
@Slf4j
@Component
public class AuthInterceptor implements AsyncHandlerInterceptor {
    // 用户缓存key
    public static final String USER_KEY = "user";

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        log.debug(">>> Interceptor:{}", request.getRequestURL());

        /**
         * 解决拦截器导致@CrossOrigin跨域失效问题:
         * CORS 复杂请求时会首先发送一个 OPTIONS 请求做嗅探，来测试服务器是否支持本次请求，请求成功后才会发送真实的请求;
         * 而 OPTIONS 请求不会携带数据，导致这个请求被拦截了，直接返回了状态码，响应头中没携带解决跨域问题的头部信息，出现了跨域问题;
         */
        if ("OPTIONS".equals(request.getMethod().toUpperCase())) {
            return true;
        }
        // 解析token
        String auth = request.getHeader("Authorization");
        if (!StringUtils.hasLength(auth)) {
            throw new CustomException("token不能为空", 400);
        }
        // 校验token
        String[] authArr = auth.split(" ");
        if (authArr.length != 2 || !"Bearer".equals(authArr[0])) {
            throw new CustomException("token格式非法", 400);
        }
        String token = authArr[1];

        // 根据token解析出用户信息
        JwtToken<UserEntity> jwtToken = JwtUtil.parseJwtToken(token);
        UserEntity userEntity = jwtToken.getUser();
        log.info(">>> {}", userEntity);
        if (userEntity == null) {
            throw new CustomException("token未解析出用户信息", 401);
        }
        if (jwtToken.getType() != TokenEnum.TOKEN) {
            throw new CustomException("refresh_token不能作为token使用", 401);
        }

        // 将用户id存入request对象
        request.setAttribute(USER_KEY, userEntity);
        return true;
    }
}
